package service

import (
	"fmt"

	"im/common"
	"im/dao"
	"im/errcode"
	"im/model"
	"im/requests"
	"im/responses"
	"im/service/push"
)

type Posts interface {
	List(userId int64, pagination requests.Pagination) ([]responses.PostsWithLiked, error)
	// 获取推荐的帖子列表,appId用来确定有哪些group
	ListRecommend(user model.Users, appId int64, pagination requests.GetRecommendPosts) ([]responses.PostsWithLiked, error)

	// 只获取帖子内容,可用于编辑
	GetById(userId, id int64) (responses.PostsWithLiked, error)

	// 获取帖子内容和评论,用于展示,这个默认为get调用的接口
	GetReplysList(userId, id int64, pagination requests.Pagination) ([]responses.ReplyWithBasicInfoAndChildren, error)
	DeleteById(userId, id int64) error
	UpdateById(userId, id int64, mm model.PostsModifiable) error

	// 创建一个新的帖子
	Create(userId int64, mm model.PostsModifiable) (int64, error)
	// 点赞
	Like(userId, postId int64) error
	Unlike(userId, postId int64) error
}

func NewPosts() Posts {
	return posts{d: dao.NewPostsWithEs()}
}

type posts struct {
	d dao.Posts
}

func (p posts) ListRecommend(user model.Users, appId int64, param requests.GetRecommendPosts) ([]responses.PostsWithLiked, error) {
	var resp = []responses.PostsWithLiked{}

	var groupIds []int64
	var err error
	// 没有组的话就直接给他返回好了

	groupIds, err = dao.NewGroupsUsersDao().GetGroupIdListByUserId(user.Id)
	if err != nil {
		return resp, err
	}

	list, err := p.d.ListRecommend(user, param, common.ToInterfaceSlice(groupIds)...)
	if err != nil {
		return resp, err
	}
	var ids = []int64{}
	for _, row := range list {
		ids = append(ids, row.Id)
	}
	likedMap, _ := p.d.GetLikedPostIdsBatch(user.Id, ids...)
	for _, row := range list {
		var liked = 0
		if _, ok := likedMap[row.Id]; ok {
			liked = 1
		}
		resp = append(resp, responses.PostsWithLiked{
			Posts: row,
			Liked: liked,
		})
	}
	return resp, nil
}

func (p posts) List(userId int64, pagination requests.Pagination) ([]responses.PostsWithLiked, error) {
	var resp = []responses.PostsWithLiked{}
	list, err := p.d.List(userId, pagination)
	if err != nil {
		return resp, err
	}
	var ids = []int64{}
	for _, row := range list {
		ids = append(ids, row.Id)
	}
	likedMap, _ := p.d.GetLikedPostIdsBatch(userId, ids...)
	for _, row := range list {
		var liked = 0
		if _, ok := likedMap[row.Id]; ok {
			liked = 1
		}
		resp = append(resp, responses.PostsWithLiked{
			Posts: row,
			Liked: liked,
		})
	}
	return resp, nil
}

func (p posts) Like(userId, postId int64) error {
	exist, err := dao.NewLikes().Like(userId, model.LikesSelector{
		PRId: postId,
		Type: model.LikesType_Post,
	})
	if err != nil {
		return err
	}
	// 如果存在, 直接静默失败
	if exist {
		return nil
	}
	return p.d.AddStat(postId, model.PostStatLikes)
}
func (p posts) Unlike(userId, postId int64) error {
	success, err := dao.NewLikes().UnLike(userId, model.LikesSelector{
		PRId: postId,
		Type: model.LikesType_Post,
	})
	if err != nil {
		return err
	}
	// 如果存在, 直接静默失败
	if !success {
		return nil
	}
	return p.d.SubStat(postId, model.PostStatLikes)
}

func (p posts) Create(userId int64, mm model.PostsModifiable) (int64, error) {
	m, err := p.d.Insert(userId, mm)
	if err != nil {
		return 0, err
	}
	if len(mm.FromGroupId) == 0 {
		return m.Id, nil
	}
	groupUsers, err := dao.NewGroupsUsersDao().GetCanPushUser(mm.FromGroupId...)
	if err != nil {
		// 静默失败
		return m.Id, nil
	}
	for _, u := range groupUsers {
		msg := fmt.Sprintf("%s里有新帖子,快去看看叭", u.Name)
		_ = push.PushMessage(u.PushToken, msg)
	}
	return m.Id, nil
}

func (p posts) GetReplysList(userId, id int64, pagination requests.Pagination) ([]responses.ReplyWithBasicInfoAndChildren, error) {
	var replyWithChildren = []responses.ReplyWithBasicInfoAndChildren{}
	var err error
	replys, err := NewReplys().GetFirstLevelReplysByPostId(userId, id, pagination)
	if err != nil {
		return replyWithChildren, err
	}
	var topReplyIds = []int64{}
	for _, row := range replys {
		topReplyIds = append(topReplyIds, row.Id)
	}
	subReplys, err := NewReplys().GetSubReplyListBatch(userId, topReplyIds...)
	if err != nil {
		return replyWithChildren, err
	}
	subReplyCounts, err := NewReplys().GetSubReplyCountBatch(topReplyIds...)
	if err != nil {
		return replyWithChildren, err
	}
	for _, row := range replys {
		var children = []responses.ReplyWithBasicInfo{}
		var count = 0
		if sub, ok := subReplys[row.Id]; ok {
			children = append(children, sub)
		}
		if cnt, ok := subReplyCounts[row.Id]; ok {
			count = cnt
		}
		replyWithChildren = append(replyWithChildren, responses.ReplyWithBasicInfoAndChildren{
			ReplyWithBasicInfo: row,
			Children:           children,
			Count:              count,
		})
	}
	return replyWithChildren, nil
}

func (p posts) GetById(userId, id int64) (responses.PostsWithLiked, error) {
	var mm = responses.PostsWithLiked{}
	m, err := p.d.GetById(id)
	if err != nil {
		return mm, err
	}
	likedMap, _ := p.d.GetLikedPostIdsBatch(userId, id)
	mm.Posts = m
	if _, ok := likedMap[m.Id]; ok {
		mm.Liked = 1
	}
	return mm, nil
}

func (p posts) DeleteById(userId, id int64) error {
	return p.d.Hide(userId, id)
}

func (p posts) UpdateById(userId, id int64, mm model.PostsModifiable) error {
	if !p.d.Belong(userId, id) {
		return errcode.NewError(errcode.UnauthorizedOperation, fmt.Errorf("%d 不属于%d", id, userId))
	}
	return p.d.Update(id, mm)
}
